/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 thread.h

	$Header: /heroes4/thread.h $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )


#include "thread.h"

#define WIN32_LEAN_AND_MEAN
// as opposed to fat and bloated?
#define NOMINMAX
#include <windows.h>

DWORD WINAPI thread_function( void* arg )
{
	t_thread* thread = reinterpret_cast<t_thread*>(arg);

	return thread->run();
}

struct t_thread::t_data
{
	HANDLE handle;
	bool   stop;
};

// ------------------------------------------------------------
// encapsulate windows threads (avoiding includes of windows.h)
// ------------------------------------------------------------
t_thread::t_thread() : m_data( new t_data )
{
	m_data->handle = 0;
	m_data->stop = false;
}

// ------------------------------------------------------------
// encapsulate windows threads (avoiding includes of windows.h)
// ------------------------------------------------------------
t_thread::~t_thread()
{
	stop();
	if (m_data->handle != 0)
		CloseHandle( m_data->handle );
}

// ------------------------------------------------------------
// encapsulate windows threads (avoiding includes of windows.h)
// ------------------------------------------------------------
t_uint32 t_thread::get_exit_code() const
{
	if (m_data->handle == 0)
		return 0;

	DWORD status;

	return GetExitCodeThread( m_data->handle, &status );
}

// ------------------------------------------------------------
// encapsulate windows threads (avoiding includes of windows.h)
// ------------------------------------------------------------
bool t_thread::is_running() const
{
	if (m_data->handle == 0)
		return false;

	return WaitForSingleObject( m_data->handle, 0 ) != WAIT_OBJECT_0;
}

// ------------------------------------------------------------
// encapsulate windows threads (avoiding includes of windows.h)
// ------------------------------------------------------------
void t_thread::stop( bool wait )
{
	m_data->stop = true;
	if (wait)
		wait_to_end();
}

// ------------------------------------------------------------
// encapsulate windows threads (avoiding includes of windows.h)
// ------------------------------------------------------------
void t_thread::wait_to_end()
{
	if (m_data->handle == 0)
		return;
	WaitForSingleObject( m_data->handle, INFINITE );
}

// ------------------------------------------------------------
// encapsulate windows threads (avoiding includes of windows.h)
// ------------------------------------------------------------
bool t_thread::stop_requested() const
{
	return m_data->stop;
}

// ------------------------------------------------------------
// encapsulate windows threads (avoiding includes of windows.h)
// ------------------------------------------------------------
void t_thread::start()
{
	DWORD thread_id;

	if (m_data->handle == 0)
		m_data->handle = CreateThread( 0, 0, thread_function, this, 0, &thread_id );
}

